package com.huang.transport.netty.client;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.huang.serializer.CommonSerializer;
import com.huangwei.entity.RpcRequest;
import com.huangwei.entity.RpcResponse;
import com.huangwei.factory.SingletonFactory;
import com.sun.java.swing.ui.CommonMenuBar;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

public class NettyClientHandler extends SimpleChannelInboundHandler<RpcResponse> {

    private static final Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);

    private final UnprocessedRequests unprocessedRequests;

    public NettyClientHandler() {
        this.unprocessedRequests = SingletonFactory.getInstance(UnprocessedRequests.class);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcResponse rpcResponse) throws Exception {
        try{
            logger.info(String.format("客户端接收到消息: %s", rpcResponse));
            unprocessedRequests.complete(rpcResponse);
        }finally {
            ReferenceCountUtil.release(rpcResponse);
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext channelHandlerContext,Throwable throwable)throws Exception{
        logger.error("调用过程中有错误发生：");
        throwable.printStackTrace();
        channelHandlerContext.close();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent){
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.WRITER_IDLE) {
                logger.error("发送心跳包[{}]", ctx.channel().remoteAddress());
                Channel channel = ChannelProvider.get((InetSocketAddress) ctx.channel().remoteAddress(),
                        CommonSerializer.getByCode(CommonSerializer.DEFAULT_SERIALIZER));
                RpcRequest rpcRequest = new RpcRequest();
                rpcRequest.setHeartBeat(true);
                channel.writeAndFlush(rpcRequest).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            }
        }else {
            super.userEventTriggered(ctx,evt);
        }
    }
}
